import React, { useEffect, useRef, useState, useCallback } from 'react'; import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; // Added .js to the import path import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, doc, setDoc, getDoc, onSnapshot } from 'firebase/firestore'; // Componente principal de la aplicación function App() { const [activeModule, setActiveModule] = useState('overview'); const [isSidebarOpen, setIsSidebarOpen] = useState(false); const [userId, setUserId] = useState(null); const [isAuthReady, setIsAuthReady] = useState(false); const [db, setDb] = useState(null); const [auth, setAuth] = useState(null); const [userProgress, setUserProgress] = useState({}); const [showModal, setShowModal] = useState(false); const [modalMessage, setModalMessage] = useState(''); // Configuración de Firebase - ¡No modificar, se inyecta en tiempo de ejecución! const firebaseConfig = typeof __firebase_config !== 'undefined' ? JSON.parse(__firebase_config) : {}; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const initialAuthToken = typeof __initial_auth_token !== 'undefined' ? __initial_auth_token : null; // Inicialización de Firebase y autenticación useEffect(() => { try { const app = initializeApp(firebaseConfig); const firestoreDb = getFirestore(app); const firebaseAuth = getAuth(app); setDb(firestoreDb); setAuth(firebaseAuth); const unsubscribe = onAuthStateChanged(firebaseAuth, async (user) => { if (user) { setUserId(user.uid); setIsAuthReady(true); } else { // Si no hay token inicial, iniciar sesión anónimamente if (!initialAuthToken) { await signInAnonymously(firebaseAuth); } // El onAuthStateChanged se disparará de nuevo con el usuario anónimo } }); // Si hay un token inicial, usarlo para iniciar sesión if (initialAuthToken) { signInWithCustomToken(firebaseAuth, initialAuthToken) .catch((error) => { console.error("Error signing in with custom token:", error); // Fallback a inicio de sesión anónimo si falla el token personalizado signInAnonymously(firebaseAuth).catch(console.error); }); } return () => unsubscribe(); } catch (error) { console.error("Error initializing Firebase:", error); setModalMessage("Error al inicializar Firebase. Algunas funcionalidades podrían no estar disponibles."); setShowModal(true); } }, [initialAuthToken, firebaseConfig]); // Cargar el progreso del usuario desde Firestore useEffect(() => { if (db && userId && isAuthReady) { const userDocRef = doc(db, `artifacts/${appId}/users/${userId}/digestive_progress`, 'progress'); const unsubscribe = onSnapshot(userDocRef, (docSnap) => { if (docSnap.exists()) { setUserProgress(docSnap.data()); } else { setUserProgress({}); // No hay progreso aún } }, (error) => { console.error("Error fetching user progress:", error); setModalMessage("Error al cargar el progreso del usuario."); setShowModal(true); }); return () => unsubscribe(); } }, [db, userId, isAuthReady, appId]); // Guardar el progreso del usuario en Firestore const saveUserProgress = useCallback(async (newProgress) => { if (db && userId && isAuthReady) { try { const userDocRef = doc(db, `artifacts/${appId}/users/${userId}/digestive_progress`, 'progress'); await setDoc(userDocRef, newProgress, { merge: true }); // Eliminado el mensaje de éxito del modal aquí } catch (error) { console.error("Error saving user progress:", error); setModalMessage("Error al guardar el progreso del usuario."); setShowModal(true); } } else { setModalMessage("No se pudo guardar el progreso. Autenticación no lista."); setShowModal(true); } }, [db, userId, isAuthReady, appId]); const handleModuleClick = (moduleName) => { setActiveModule(moduleName); setIsSidebarOpen(false); // Cerrar sidebar al seleccionar módulo // Ejemplo de cómo podrías guardar el progreso al cambiar de módulo saveUserProgress({ lastModuleVisited: moduleName }); }; const closeModal = () => setShowModal(false); return ( // La estructura de la aplicación está diseñada para ser autocontenida y embeddable. // Puede ser montada en cualquier elemento DOM y se adaptará a su contenedor.
{/* Modal de Mensajes */} {showModal && (

{modalMessage}

)} {/* Encabezado */}

Anatomía Digestiva Interactiva

{userId && (
ID de Usuario: {userId}
)}
{/* Contenido Principal */}
{/* Barra Lateral (Sidebar) */} {/* Área de Contenido Principal */}
{activeModule === 'overview' && (

Visión General del Sistema Digestivo

Explora el fascinante viaje de los alimentos a través de tu cuerpo.

El sistema digestivo es un conjunto de órganos que trabajan en conjunto para transformar los alimentos que consumes en nutrientes que tu cuerpo puede usar para energía, crecimiento y reparación.

Este módulo te ofrece un mapa interactivo del trayecto digestivo, destacando los principales órganos y sus funciones.

{/* Aquí iría el mapa esquemático interactivo */}
[Mapa esquemático interactivo del trayecto digestivo con puntos interactivos]
)} {activeModule === 'macroscopic' && (

Órganos Macroscópicos

Sumérgete en la anatomía visible de cada componente del sistema digestivo.

Desde la boca hasta el ano, cada órgano tiene una estructura única que le permite cumplir su función específica en la digestión.

  • Tubo Digestivo Principal:
    • Boca: Dientes, lengua, glándulas salivales (parótida, submandibular, sublingual).
    • Faringe: Nasofaringe, orofaringe, laringofaringe.
    • Esófago: Tubo muscular que conecta la faringe con el estómago. Capas de la pared (mucosa, submucosa, muscular, adventicia/serosa).
    • Estómago: Órgano en forma de J. Regiones anatómicas (cardias, fundus, cuerpo, antro pilórico, píloro). Curvaturas mayor y menor.
    • Intestino Delgado: Tubo largo y enrollado.
      • Duodeno: Primera sección, en forma de C.
      • Yeyuno: Sección media, principal lugar de absorción.
      • Íleon: Última sección, se une al intestino grueso.
      Características: Pliegues circulares (válvulas de Kerckring), vellosidades y microvellosidades.
    • Intestino Grueso:
      • Ciego: Bolsa inicial con el apéndice vermiforme.
      • Colon: Ascendente, transverso, descendente, sigmoides. Haustras y tenias cólicas.
      • Recto: Almacena heces antes de la defecación.
      • Ano: Abertura terminal con esfínteres interno y externo.
  • Órganos Accesorios:
    • Hígado: Glándula más grande del cuerpo. Lobulillos hepáticos, vías biliares.
    • Vesícula Biliar: Almacena y concentra la bilis.
    • Páncreas: Glándula exocrina (enzimas digestivas) y endocrina (hormonas). Acinos pancreáticos y conductos.
{/* Aquí irían modelos 3D interactivos de órganos individuales */}
[Modelos 3D interactivos de órganos individuales con hotspots y fichas informativas]
)} {activeModule === 'microanatomy' && (

Microanatomía e Histología

Explora el mundo microscópico de los tejidos digestivos.

La función del sistema digestivo se basa en la intrincada estructura de sus células y tejidos, invisibles a simple vista.

  • Vellosidades y Microvellosidades: Propósito y estructura.
  • Criptas de Lieberkühn, Glándulas Gástricas y Acinos Pancreáticos.
{/* Aquí irían cortes histológicos interactivos con zoom */}
[Cortes histológicos interactivos con zoom, leyendas y herramienta de comparación]
)} {activeModule === 'vascularization' && (

Vascularización y Drenaje Linfático

Comprende cómo los nutrientes son transportados y cómo el sistema inmune protege el tracto digestivo.

  • Redes Arteriales y Venosas: Diagramas interactivos.
  • Plexos Nerviosos y Ganglios Linfáticos Asociados.
{/* Aquí irían infografías interactivas */}
[Infografías interactivas de rutas vasculares y linfáticas]
)} {activeModule === '3d-integration' && (

Integración 3D y Capas Anatómicas

Manipula un modelo 3D completo del sistema digestivo, aislando órganos y explorando sus capas.

Usa el ratón para rotar el modelo. Haz clic y arrastra para mover la cámara. Usa la rueda del ratón para hacer zoom.

{/* Controles para el modelo 3D (ej. selección de capas, cortes) */}

Progreso actual del usuario: {JSON.stringify(userProgress)}

)}
{/* Pie de página */}
); } // Componente para el renderizado 3D con Three.js function DigestiveSystem3D() { const mountRef = useRef(null); useEffect(() => { const currentMount = mountRef.current; if (!currentMount) return; // Configuración de la escena const scene = new THREE.Scene(); scene.background = new THREE.Color(0xf0f0f0); // Color de fondo claro // Configuración de la cámara const camera = new THREE.PerspectiveCamera(75, currentMount.clientWidth / currentMount.clientHeight, 0.1, 1000); camera.position.z = 5; // Configuración del renderizador const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(currentMount.clientWidth, currentMount.clientHeight); renderer.setPixelRatio(window.devicePixelRatio); currentMount.appendChild(renderer.domElement); // Añadir controles de órbita para interactividad const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; // para un movimiento más suave controls.dampingFactor = 0.05; controls.screenSpacePanning = false; controls.minDistance = 2; controls.maxDistance = 10; // Añadir un modelo 3D de ejemplo (un cubo para representar un órgano) const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshPhongMaterial({ color: 0x007bff }); // Material con luz const cube = new THREE.Mesh(geometry, material); scene.add(cube); // Añadir luces para que el modelo sea visible const ambientLight = new THREE.AmbientLight(0x404040); // Luz ambiental suave scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); // Luz direccional directionalLight.position.set(1, 1, 1).normalize(); scene.add(directionalLight); // Función de animación const animate = () => { requestAnimationFrame(animate); controls.update(); // solo si enableDamping está activado renderer.render(scene, camera); }; animate(); // Manejar el redimensionamiento de la ventana const handleResize = () => { camera.aspect = currentMount.clientWidth / currentMount.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(currentMount.clientWidth, currentMount.clientHeight); }; window.addEventListener('resize', handleResize); // Limpieza al desmontar el componente return () => { window.removeEventListener('resize', handleResize); if (currentMount) { currentMount.removeChild(renderer.domElement); } renderer.dispose(); geometry.dispose(); material.dispose(); controls.dispose(); // Disponer de los controles de órbita // Limpiar la escena si es necesario, aunque Three.js suele manejarlo }; }, []); // El array de dependencias vacío asegura que se ejecute una sola vez return
; } export default App;